/*
 *  Copyright 2010 Miao.
 * 
 *  Licensed under the Apache License, Version 2.0 (the "License");
 *  you may not use this file except in compliance with the License.
 *  You may obtain a copy of the License at
 * 
 *       http://www.apache.org/licenses/LICENSE-2.0
 * 
 *  Unless required by applicable law or agreed to in writing, software
 *  distributed under the License is distributed on an "AS IS" BASIS,
 *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 *  See the License for the specific language governing permissions and
 *  limitations under the License.
 *  under the License.
 *
 *  @(#)SecurityCodeImageImpl.java    0.2 01/17/2010
 */
package image;

import java.awt.Color;
import java.awt.Graphics2D;
import java.awt.image.BufferedImage;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Random;

import javax.imageio.ImageIO;

/**
 * 验证码图像引擎实现
 * @author Miao
 * @version 0.2
 * @since 0.2
 */
public class SecurityCodeImageImpl implements SecurityCodeImage {

    /**
     * 验证码图形参数
     */
    private final SecurityCodeProperty property;
    /**
     * 随机数生成器
     */
    private Random random;

    /**
     * 构造方法
     * @param property 验证码图形参数.
     * @since 0.2
     */
    public SecurityCodeImageImpl(SecurityCodeProperty property) {
        this.property = property;
        random = new Random();
    }

    public void exportSecurityCode(String securityCode, OutputStream output) throws IOException {
        try {
            ImageIO.write(drawImage(securityCode), property.getFormatName(), output);
        } finally {
            output.close();
        }


    }

    /**
     * 绘制验证码
     * @param securityCode 验证码
     * @return 图形对象
     * @since 0.2
     */
    public BufferedImage drawImage(String securityCode) {
        BufferedImage img = new BufferedImage(property.getWidth(), property.getHeight(), BufferedImage.TYPE_INT_RGB);
        Graphics2D graphics = img.createGraphics();
        drawBackground(graphics);
        drawInterfering(graphics);
        drawCode(graphics, securityCode);
        return img;
    }

    /**
     * 绘制背景
     * @param graphics 绘图对象
     * @since 0.2
     */
    private void drawBackground(Graphics2D graphics) {
        graphics.setColor(property.getBackgroundColor());
        graphics.fillRect(0, 0, property.getWidth(), property.getHeight());
    }

    /**
     * 绘制干扰线以防止OCR
     * @param graphics 绘图对象
     * @since 0.2
     */
    private void drawInterfering(Graphics2D graphics) {
        for (int i = 0; i < property.getInterferingLine(); i++) {
            int x = random.nextInt(property.getWidth());
            int y = random.nextInt(property.getHeight());
            int ex = random.nextInt(property.getHeight() / 2);
            int ey = random.nextInt(property.getHeight() / 2);
            if (i % 5 == 0) {
                graphics.setColor(getRandomColor());
            }
            graphics.drawLine(x, y, x + ex, y + ey);
        }
    }

    /**
     * 绘制验证码
     * @param graphics 绘图对象
     * @param securityCode 验证码
     * @since 0.2
     */
    private void drawCode(Graphics2D graphics, String securityCode) {
        graphics.setFont(property.getFont());
        for (int i = 0; i < property.getCodeLength(); i++) {
            graphics.setColor(getRandomTextColor());
            graphics.drawString(securityCode.substring(i, i + 1), (i + 1) * property.getCodeX(), property.getCodeY());
        }
    }

    /**
     * 获得随机颜色
     * @return 随机颜色
     * @since 0.2
     */
    private Color getRandomColor() {
        return new Color(random.nextInt(125), random.nextInt(255), random.nextInt(125));
    }

    /**
     * 获得随机文字颜色
     * @return 随机文字颜色
     * @since 0.2
     */
    private Color getRandomTextColor() {
        switch (random.nextInt(3)) {
            case 0 : return Color.RED;
            case 1 : return Color.BLUE;
            case 2 :
            default : return Color.BLACK;
        }

    }
}
